import 'package:flutter/material.dart';

class ScannerOverlayShape extends ShapeBorder {
  final Rect scanWindow;

  const ScannerOverlayShape(this.scanWindow);

  @override
  EdgeInsetsGeometry get dimensions => EdgeInsets.zero;

  @override
  Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
    return Path()
      ..fillType = PathFillType.evenOdd
      ..addPath(getOuterPath(rect), Offset.zero);
  }

  @override
  Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
    Path getLeftTopPath(Rect rect) {
      return Path()
        ..moveTo(rect.left, rect.bottom)
        ..lineTo(rect.left, rect.top)
        ..lineTo(rect.right, rect.top);
    }

    return getLeftTopPath(rect)
      ..lineTo(
        rect.right,
        rect.bottom,
      )
      ..lineTo(
        rect.left,
        rect.bottom,
      )
      ..lineTo(
        rect.left,
        rect.top,
      );
  }

  @override
  void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
    final width = rect.width;
    final height = rect.height;
    final cutOutWidth = scanWindow.right - scanWindow.left;
    final cutOutHeight = scanWindow.bottom - scanWindow.top;
    final cutOutBoxWidth = cutOutWidth < width ? cutOutWidth : width;
    final cutOutBoxHeight = cutOutHeight < height ? cutOutHeight : height;

    final backgroundPaint = Paint()
      ..color = Colors.black.withOpacity(0.7)
      ..style = PaintingStyle.fill;

    final boxPaint = Paint()
      ..style = PaintingStyle.fill
      ..blendMode = BlendMode.dstOut;

    final cutOutRect = Rect.fromLTWH(
      rect.left + width / 2 - cutOutBoxWidth / 2,
      rect.top + height / 2 - cutOutBoxHeight / 2,
      cutOutBoxWidth,
      cutOutBoxHeight,
    );

    canvas
      ..saveLayer(
        rect,
        backgroundPaint,
      )
      ..drawRect(
        rect,
        backgroundPaint,
      )
      ..drawRect(
        cutOutRect,
        boxPaint,
      )
      ..restore();
  }

  @override
  ShapeBorder scale(double t) {
    return ScannerOverlayShape(scanWindow);
  }
}
